﻿using System;
using System.Security.Cryptography;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Text;

namespace UdpaySecurity
{
    /// <summary>
    /// Description of MyClass.
    /// </summary>


    public static class UdpayRsa
    {
        public struct SignKeyParams
        {
            public static string MPK;
            public static string Wht_n;
            public static string Wht_e;
            public static string message;
            public static RSAParameters RSAParams1 = new RSAParameters();
            public static RSAParameters RSAParams2 = new RSAParameters();
        }

        //装载解析RSA密钥
        public static bool LoadSignKey()
        {
            try
            {
                //此处值，可以补充函数写成页面传参，直接为SignKeyParams内的变量赋值即可
                //本例中采用直接写入方法，下面是测试密钥，正式时需要更换密钥的值
                
                string MPK_Str = "wht.privateKey=30820276020100300d06092a864886f70d0101010500048202603082025c02010002818100c53dd6b55a26b777876e3be3fbde68bd7170f5eaed91f63b66b10280030c49dd05b54bb1cdc714a6d7bd6a4a899685cd9b9bcca41d2ae49044aef3ab54f45e4ffdc47d0e6f973de6185cb7797b033f6798667ba521b01d6150cdb470d4247669f40b6400ad66defed973c5a55040b63c35f5aa8c2adb142452ec228d209830fd02030100010281806267d4cc4bfb0f03d28cbbd2a5e1b3cdf8600c41365fe142879c7e8bd1797b0c8b81850f638414989d00429c878292a51f229ef9ae17ad4b11095c46b9aee5b20fc114f3d2ca6117e183d60e272b77884e6ffe56d9874449ddd411a7665d3d96a191df7b708c09502560fc8edb0d449aa6f49dd5b2a762b61b7f44117142f541024100f74640dc776b76f4365ed13dcc205cdc1467a151427e08ab845d48924cb588ec9477737a20bdc075a7dee29b4ae5b11a3af66d14c8fef9ee86d64691d8dc70cd024100cc339d641279f68bc421e7102a4c198073eb55f2c1976d4aaac7e16acb333c797114a3cf5efed65ccb920995b79fa7e46bbb3c2a07fa141b6d0a647d955a00f10240204462a26252fbaad28d7cf07b7a9da37a662b7ed7166b3b368295bdc194ced1506e65fb41da810ad965145cff6109c34a7e6dad90acf520532812fd65371ee102400facfaad1ef9fbe238d93d6ab1448c449f2176c49ef5e7eeee734fabaa13b1d5c4c787d7b87c29aa8ffa13004a4b585121b00aeb53177089b67230caaf376c91024100d9f81fd72e39f27768714159b1024c5c3f579ad1c8b5cc13d622f2a69e486f6c550c5c6086e65876c6d77eb447fc552d13c79a1f48835ef99c66c4379a6eb6da" ;
                string Wht_n_Str = "wht.publicModulus=00c53dd6b55a26b777876e3be3fbde68bd7170f5eaed91f63b66b10280030c49dd05b54bb1cdc714a6d7bd6a4a899685cd9b9bcca41d2ae49044aef3ab54f45e4ffdc47d0e6f973de6185cb7797b033f6798667ba521b01d6150cdb470d4247669f40b6400ad66defed973c5a55040b63c35f5aa8c2adb142452ec228d209830fd" ;
                string Wht_e_Str = "wht.publicExponent=010001" ;

                //************需要注意的地方--密钥必须是大写,用ToUpper()函数************************
                SignKeyParams.MPK = MPK_Str.ToUpper();
                SignKeyParams.Wht_n = Wht_n_Str.ToUpper();
                SignKeyParams.Wht_e = Wht_e_Str.ToUpper();

                //开始解析私钥
                char[] n = new char[256];
                char[] e = new char[6];
                char[] d = new char[256];
                char[] dp = new char[128];
                char[] dq = new char[128];
                char[] iq = new char[128];
                char[] p = new char[128];
                char[] q = new char[128];
                AnysysPK(SignKeyParams.MPK, n, e, d, dq, dp, iq, p, q);
                //准备自己的私钥


                SignKeyParams.RSAParams1.Exponent = Translate2CtoB(e);
                SignKeyParams.RSAParams1.Modulus = Translate2CtoB(n);
                SignKeyParams.RSAParams1.D = Translate2CtoB(d);
                SignKeyParams.RSAParams1.DP = Translate2CtoB(dp);
                SignKeyParams.RSAParams1.DQ = Translate2CtoB(dq);
                SignKeyParams.RSAParams1.InverseQ = Translate2CtoB(iq);
                SignKeyParams.RSAParams1.P = Translate2CtoB(p);
                SignKeyParams.RSAParams1.Q = Translate2CtoB(q);

                //解析网汇通公钥并赋值

                int length_str = 0;
                int index_str = 0;
                index_str = SignKeyParams.Wht_e.IndexOf("=", 0);
                if (SignKeyParams.Wht_e[index_str + 1].Equals(SignKeyParams.Wht_e[index_str + 2]) &&
                   SignKeyParams.Wht_e[index_str + 1].Equals('0'))
                {
                    index_str = index_str + 3;
                    length_str = SignKeyParams.Wht_e.Length - index_str;

                }
                else
                {
                    index_str = index_str + 1;
                    length_str = SignKeyParams.Wht_e.Length - index_str;
                }
                char[] char_WhtPublicKey_e = new char[length_str];
                SignKeyParams.Wht_e.CopyTo(index_str, char_WhtPublicKey_e, 0, length_str);

                index_str = SignKeyParams.Wht_n.IndexOf("=", 0);
                if (SignKeyParams.Wht_n[index_str + 1].Equals(SignKeyParams.Wht_n[index_str + 2]) &&
                  SignKeyParams.Wht_n[index_str + 1].Equals('0'))
                {
                    index_str = index_str + 3;
                    length_str = SignKeyParams.Wht_n.Length - index_str;
                }
                else
                {
                    index_str = index_str + 1;
                    length_str = SignKeyParams.Wht_n.Length - index_str;
                }
                char[] char_WhtPublicKey_n = new char[length_str];
                SignKeyParams.Wht_n.CopyTo(index_str, char_WhtPublicKey_n, 0, length_str);


                SignKeyParams.RSAParams2.Exponent = Translate2CtoB(char_WhtPublicKey_e);
                SignKeyParams.RSAParams2.Modulus = Translate2CtoB(char_WhtPublicKey_n);

                return true;
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                Console.WriteLine("The key could not be read:");
                Console.WriteLine(e.Message);
                return false;
            }
        }
        public static string GenerateSigature(string PText)
        {
            string SignedData = SignData(PText);
            return SignedData;
        }

        public static int VerifySigature(string PText, string Sign)
        {

            if (VerifyData(PText, Sign))
                return 0;
            return -1;

        }

        private static string SignData(string str_DataToSign)
        {

            Encoding ByteConverter = Encoding.GetEncoding(936);
            byte[] DataToSign = ByteConverter.GetBytes(str_DataToSign);
            //开始加密			
            RSACryptoServiceProvider RSAalg1 = new RSACryptoServiceProvider();
            RSAalg1.ImportParameters(SignKeyParams.RSAParams1);
            MD5CryptoServiceProvider MD5alg1 = new MD5CryptoServiceProvider();
            byte[] SignedData = RSAalg1.SignData(DataToSign, MD5alg1);
            //签名结果格式转换
            string sss = TransBtoS(SignedData);
            //返回签名结果字符串,小写字符
            return sss;
        }

        private static bool VerifyData(string str_DataToSign, string str_SignedData)
        {
            //格式化需要验证的数据
            //ASCIIEncoding ByteConverter1 = new ASCIIEncoding();
            Encoding ByteConverter1 = Encoding.GetEncoding(936);
            byte[] DataToVerify = ByteConverter1.GetBytes(str_DataToSign);

            //格式化签名数据
            char[] char_SignedData = new char[str_SignedData.Length];
            str_SignedData = str_SignedData.ToUpper();
            str_SignedData.CopyTo(0, char_SignedData, 0, str_SignedData.Length);
            byte[] SignedData = Translate2CtoB(char_SignedData);


            //开始签名验证
            RSACryptoServiceProvider RSAalg1 = new RSACryptoServiceProvider();
            RSAalg1.ImportParameters(SignKeyParams.RSAParams2);
            MD5CryptoServiceProvider MD5alg1 = new MD5CryptoServiceProvider();
            //返回签名验证结果
            return RSAalg1.VerifyData(DataToVerify, MD5alg1, SignedData);
        }

        private static void AnysysPK(string pk, char[] n, char[] e, char[] d, char[] dq,
                                 char[] dp, char[] iq, char[] p, char[] q)
        {
            int index = 0;
            int index_tmp = 0;
            //取出moudules-n
            index = pk.IndexOf("02818100", 0);
            if (index == -1)
            {
                index = pk.IndexOf("028180", 0) + 6;
            }
            else
            {
                index = index + 8;
            }
            pk.CopyTo(index, n, 0, 256);
            index = index + 256;
            index_tmp = index;
            //取出-e
            index = pk.IndexOf("02818100", index_tmp, 30);
            if (index == -1)
            {
                index = pk.IndexOf("028180", 0) - 6;
                index_tmp = index + 12;
            }
            else
            {
                index = index - 6;
                index_tmp = index + 14;
            }
            pk.CopyTo(index, e, 0, 6);

            //取出d
            pk.CopyTo(index_tmp, d, 0, 256);
            //取出p
            index = index_tmp + 256;
            index_tmp = index;
            index = pk.IndexOf("0240", index_tmp, 6);
            if (index == -1)
            {
                index = pk.IndexOf("024100", index_tmp, 6) + 6;
            }
            else
            {
                index = index + 4;
            }
            pk.CopyTo(index, p, 0, 128);
            index = index + 128;
            index_tmp = index;
            //取出q
            index = pk.IndexOf("0240", index_tmp, 6);
            if (index == -1)
            {
                index = pk.IndexOf("024100", index_tmp, 6) + 6;
            }
            else
            {
                index = index + 4;
            }
            pk.CopyTo(index, q, 0, 128);
            index = index + 128;
            index_tmp = index;
            //取出dp
            index = pk.IndexOf("0240", index_tmp, 6);
            if (index == -1)
            {
                index = pk.IndexOf("024100", index_tmp, 6) + 6;
            }
            else
            {
                index = index + 4;
            }
            pk.CopyTo(index, dp, 0, 128);
            index = index + 128;
            index_tmp = index;
            //取出dq
            index = pk.IndexOf("0240", index_tmp, 6);
            if (index == -1)
            {
                index = pk.IndexOf("024100", index_tmp, 6) + 6;
            }
            else
            {
                index = index + 4;
            }
            pk.CopyTo(index, dq, 0, 128);
            index = index + 128;
            index_tmp = index;
            //取出iq
            index = pk.IndexOf("0240", index_tmp, 6);
            if (index == -1)
            {
                index = pk.IndexOf("024100", index_tmp, 6) + 6;
            }
            else
            {
                index = index + 4;
            }
            pk.CopyTo(index, iq, 0, 128);
        }

        private static byte[] Translate2CtoB(char[] title)
        {

            byte[] byte_sss = new byte[title.Length / 2];
            int aaa1 = 0;
            int aaa2 = 0;
            for (int i = 0; i < title.Length / 2; i++)
            {

                if (title[2 * i] <= '9')
                {
                    aaa1 = Convert.ToInt16(title[2 * i]) - 48;
                }
                else
                {
                    aaa1 = Convert.ToInt16(title[2 * i]) - 55;
                }
                if (title[2 * i + 1] <= '9')
                {
                    aaa2 = Convert.ToInt16(title[2 * i + 1]) - 48;
                }
                else
                {
                    aaa2 = Convert.ToInt16(title[2 * i + 1]) - 55;
                }
                byte_sss[i] = Convert.ToByte(aaa1 * 16 + aaa2);
            }
            return byte_sss;
        }

        private static string TransBtoS(byte[] bytes)
        {
            char c1 = '0';
            char c2 = '1';
            int i1 = 0;
            int i2 = 0;
            string ccc = null;
            for (int i = 0; i < bytes.Length; i++)
            {
                i1 = Convert.ToInt16(bytes[i]);
                i2 = i1 / 16;
                if (i2 <= 9)
                    c1 = Convert.ToChar(i2 + 48);
                else
                    c1 = Convert.ToChar(i2 + 55);
                i2 = i1 % 16;
                if (i2 <= 9)
                    c2 = Convert.ToChar(i2 + 48);
                else
                    c2 = Convert.ToChar(i2 + 55);
                ccc = ccc + Convert.ToString(c1) + Convert.ToString(c2);
            }
            return ccc.ToLower();
        }
    }

}



